﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "Color.h"
#include "OwnerPtr.h"
#include "GcmpRenderingInterface.h"
#include "GraphicsNodeType.h"

namespace gcmp
{
    class IModelView;
    class IElement;

    // 颜色混合设置类
    class GCMP_RENDERING_INTERFACE_EXPORT ColorBlendSettings
    {
    public:
        /// \brief 颜色混合类型
        enum class ColorBlendType : int32_t
        {
            None = -1,///< 默认(未设置)
            Face = 0, ///< 面
            Line = 1, ///< 线
            Text = 2, ///< 文字
            Fill = 3  ///< 填充  
        };

        /// \brief 颜色混合数据信息
        struct ColorBlendData
        {
            Color  BlendColor;           ///< 用来混合的颜色
            double RgbBlendFactor = 0.0; ///< 混合颜色的比重，只影响RGB值，A值直接相乘
        };

    public:
        /// \brief 设置颜色混合数据
        ///   注意：线与面独立混色需调用此接口，将不同类型混色数据传入，目前仅支持 面、线、文字、填充 类型。 只对设置的类型起效，没设置的保持自身颜色。
        ///        例如一个构件只包含面和线，若只设置了面类型混色数据，则该构件的面节点有混色效果，线节点保持自身颜色不变。
        /// \param datas 混色数据
        void SetColorBlendDatas(const std::map<ColorBlendType, ColorBlendData>& datas);

        /// \brief 获取颜色混合数据
        /// \return 混色数据
        const std::map<ColorBlendType, ColorBlendData>& GetColorBlendDatas() const { return m_datas; }

        /// \brief 创建颜色混合设置
        /// \param rgbBlendFactor 需在[0.0,1.0]范围内，否则创建失败
        /// \return 颜色混合设置
        static OwnerPtr<ColorBlendSettings> Create(const Color& color, double rgbBlendFactor);

        /// \brief 得到与源颜色进行混合后的颜色
        /// 混合算法：BlendColor的rgb值按比重与原颜色的rgb值混合，alpha值直接相乘
        /// \param type 颜色混合类型
        /// \return 混合后的颜色
        Color MakeBlendColor(const Color& sourceColor, ColorBlendType type = ColorBlendType::None) const;

        /// \brief 得到与源颜色进行混合后的颜色
        /// \param objID 图形节点类型数值
        /// \return 混合后的颜色
        Color MakeBlendColor(const Color& sourceColor, GraphicsNodeType nodeType) const;

        /// \brief 用来混合的颜色
        /// \return 用来混合的颜色
        gcmp::Color GetBlendColor() const;

        /// \brief 混合颜色的比重
        /// \return 混合颜色的比重，只影响RGB值，A值直接相乘
        double GetRgbBlendFactor() const;

        /// \brief 是否设置了多种颜色混合类型
        /// \return true 设置了多种不同类型的混色数据
        bool IsSetColorBlendDatas() const;

        bool operator== (const ColorBlendSettings& another) const;
        bool operator!= (const ColorBlendSettings& another) const;

    private:
        ColorBlendSettings(const Color& color, double rgbBlendFactor);
        ColorBlendData m_data;
        std::map<ColorBlendType, ColorBlendData> m_datas;
    };


    /// \brief 颜色混合器接口
    ///
    class GCMP_RENDERING_INTERFACE_EXPORT IColorBlender
    {
    public:
        /// \brief 析构函数
        virtual ~IColorBlender();

        /// \brief 获取颜色混合设置
        ///
        /// \return 颜色混合设置
        virtual gcmp::OwnerPtr<ColorBlendSettings> GetColorBlendSettings(const IModelView& modelView, const IElement& element) = 0;

        /// \brief 设置颜色混合值
        /// \param rgbBlendFactor 需在[0.0,1.0]范围内，否则创建失败
        virtual bool SetRgbBlendFactor(double rgbBlendFactor) = 0;

        /// \brief 通知用户程序即将开始收集图元颜色混合器，产品可以做些预处理
        /// 
        /// 该接口在场景"全量刷新”和“增量刷新”时会被调用，通知用户程序将开始对大量对象、分别收集颜色混合器
        /// \param modelView 视图
        virtual void StartColorBlendSettingCollection(const IModelView& modelView);

        /// \brief 通知用户程序已经结束收集图元的颜色混合器，产品可以做些后处理
        /// \param modelView 视图
        virtual void EndColorBlendSettingCollection(const IModelView& modelView);
    };
}

